package com.mytest.example.asyncservlet.controller;

import cn.hutool.core.convert.Convert;
import com.mytest.example.asyncservlet.model.ApiResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.WebAsyncTask;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;


@Slf4j
@RequestMapping("/callableResult")
@RestController
public class CallableResultController {
    public CallableResultController() {
    }

    @GetMapping("/callable")
    public Callable<ApiResult<Object>> callable() {
        log.info("线程ID={},Name={},请求进来了", Thread.currentThread().getId(), Thread.currentThread().getName());
        Callable<ApiResult<Object>> callable = buildCallable();
        log.info("线程ID={},Name={},请求出去了", Thread.currentThread().getId(), Thread.currentThread().getName());
        return callable;
    }

    @GetMapping("/webAsyncTask")
    public WebAsyncTask<?> webAsyncTask(HttpServletRequest request) {
        log.info("线程ID={},Name={},请求进来了", Thread.currentThread().getId(), Thread.currentThread().getName());
        String timeOut = request.getParameter("timeout");
        if (timeOut == null) {
            timeOut = "15";
        }
        long timeoutMillis = TimeUnit.SECONDS.toMillis(Convert.toLong(timeOut));
        log.info("超时时间 {} 毫秒", timeoutMillis);
        WebAsyncTask<ApiResult<Object>> task = new WebAsyncTask<>(timeoutMillis, buildCallable());
        task.onCompletion(() -> {
            log.info("线程ID={},Name={},调用完成了", Thread.currentThread().getId(), Thread.currentThread().getName());
        });
        task.onTimeout(() -> {
            log.info("线程ID={},Name={},调用超时了", Thread.currentThread().getId(), Thread.currentThread().getName());
            return ApiResult.fail("webAsyncTask超时了");
        });
        task.onError(() -> {
            log.info("线程ID={},Name={},发生异常了", Thread.currentThread().getId(), Thread.currentThread().getName());
            return ApiResult.fail("webAsyncTask发生错误了");
        });
        log.info("线程ID={},Name={},请求出去了", Thread.currentThread().getId(), Thread.currentThread().getName());
        return task;
    }

    private Callable<ApiResult<Object>> buildCallable() {
        return () -> {
            try {
                log.info("线程ID={},Name={},执行开始", Thread.currentThread().getId(), Thread.currentThread().getName());
                TimeUnit.SECONDS.sleep(10); //模拟处理业务逻辑，耗时10秒钟
                log.info("线程ID={},Name={},执行结束", Thread.currentThread().getId(), Thread.currentThread().getName());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            return ApiResult.success("callable执行成功");
        };
    }
}
